package com.xmall.product.define.config;

import com.alibaba.fastjson.JSON;
import com.xmall.annotation.LoginRequiredFalse;
import com.xmall.define.base.Result;
import com.xmall.define.base.ResultCode;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.annotation.Resource;
import java.util.Map;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ExceptionHandlingConfigurer<HttpSecurity> configurer = http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
                .and().exceptionHandling().authenticationEntryPoint((req, resp, e) -> {
                    resp.setStatus(HttpStatus.OK.value());
                    resp.setCharacterEncoding("UTF-8");
                    resp.setContentType("application/json;charset=UTF-8");
                    resp.getWriter().write(JSON.toJSONString(Result.error(ResultCode.NOT_LOGIN)));
                });

        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorize = configurer.and().authorizeRequests();

        // 权限及白名单
        Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
        handlerMethodMap.forEach((info, method) -> {
            if (method.getMethodAnnotation(LoginRequiredFalse.class) != null) {
                info.getPathPatternsCondition().getPatterns().forEach(pattern -> {
                    authorize.antMatchers(pattern.getPatternString()).permitAll();
                });
            }
        });

        authorize.anyRequest().authenticated();
    }
}
